/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

const rightVideo = document.getElementById('rightVideo');

class WSConnection {
  constructor() {
    this._onReceiveOffer = null;
    this._onReceiveAnswer = null;
    this._onIceCandidate = null;
    this._onGetAllPlayers = null;
  }

  connect(url, name) {
    return new Promise((resolve) => {
      this._ws = new WebSocket(url);
      this._ws.onmessage = (event) => this._onMessage(event);
      this._ws.onopen = () => {
        this.sendToServer({ type: 'handShake', name });
        resolve();
      };
    });
  }

  sendToServer(data) {
    this._ws?.send(JSON.stringify({ to: '__server__', data }));
  }

  sendToPeer(name, data) {
    this._ws?.send(JSON.stringify({ to: name, data }));
  }

  sendOffer(name, offer) {
    this.sendToPeer(name, { type: 'offer', offer });
  }

  sendAnswer(name, answer) {
    this.sendToPeer(name, { type: 'answer', answer });
  }

  sendIceCandidate(name, iceCandidate) {
    this.sendToPeer(name, { type: 'iceCandidate', iceCandidate });
  }

  set onReceiveOffer(callback) {
    this._onReceiveOffer = callback;
  }

  set onIceCandidate(callback) {
    this._onIceCandidate = callback;
  }

  set onReceiveAnswer(callback) {
    this._onReceiveAnswer = callback;
  }

  set onGetAllPlayers(callback) {
    this._onGetAllPlayers = callback;
  }

  _onMessage(event) {
    try {
      const data = JSON.parse(event.data);
      switch (data.type) {
        case 'allPlayers':
          this._onGetAllPlayers && this._onGetAllPlayers(data.players);
          break;
        case 'offer':
          this._onReceiveOffer && this._onReceiveOffer(data.offer);
          break;
        case 'answer':
          this._onReceiveAnswer && this._onReceiveAnswer(data.answer);
          break;
        case 'iceCandidate':
          this._onIceCandidate && this._onIceCandidate(data.iceCandidate);
          break;
        default:
          break;
      }
    } catch (err) {
      console.error('receive message error', err);
    }
  }
}

const ws = new WSConnection();

async function initPc2() {
  const pc2 = new RTCPeerConnection();
  console.log('Created remote peer connection object pc2');
  pc2.onicecandidate = (e) => {
    if (!e.candidate) return;
    ws.sendIceCandidate('push', e.candidate);
  };
  // pc2.oniceconnectionstatechange = (e) => onIceStateChange(pc2, e);
  pc2.ontrack = gotRemoteStream;

  await ws.connect('ws://127.0.0.1:8079', 'pull');

  ws.onReceiveOffer = async (offer) => {
    console.log('offer is', offer);
    pc2.setRemoteDescription(offer);
    const answer = await pc2.createAnswer();
    pc2.setLocalDescription(answer);
    ws.sendAnswer('push', answer);
  };

  ws.onIceCandidate = (candidate) => {
    try {
      pc2.addIceCandidate(candidate);
    } catch (err) {
      console.error('addIceCandidate error', err);
    }
  };
}

function gotRemoteStream(event) {
  if (rightVideo.srcObject !== event.streams[0]) {
    rightVideo.srcObject = event.streams[0];
    rightVideo.play();
    console.log('pc2 received remote stream', event);
  }
}

async function main() {
  await initPc2();
}

main();
